# coding=utf-8

import os
from typing import Dict
import xlrd
from generator.libsomeip.SomeIPPropertyReadImpl import gen_SomeIPReadDirectTransmitProperty
from generator.libsomeip.SomeIPPropertyWriteImpl import gen_SomeIPWriteDirectTransmitProperty
from generator.libsomeip.Android_bp import gen_someip_Android_bp
from generator.libsomeip.ConvertSignal2SomeIP import gen_convert2someIp
from generator.libsomeip.ConvertSomeIP2Signal import gen_someip2SignalValue
from generator.libsomeip.SomeIPConfig import gen_SomeIPConfig
from generator.libsomeip.NetSomeIP import gen_NetSomeIP
from generator.libsomeip.ProtoBuf import gen_SomeIPProtoBuf
from generator.libsomeip.SomeIPManager import gen_someip_manager
from generator.libsomeip.SomeIP_JSON_Config import gen_SomeIPConfigJson
from generator.libsomeip.some_ip_signals import gen_someip_signal_id
from generator.libsomeip.some_ip_type import Item, Message, SomeIP, IdtItem, EnumItem
from generator.types_hal.property import Property, TypesHal
from generator.libsomeip.WireShark_someip_lua import gen_someip_object

from utils.payload import  EncodeType, TypeEnum
from utils.util import copyPackageTo, parseCustomData, parseEncodeName, removeDir


def revertEnumMember(member,isStruct)->str:
    if isStruct:
        return member
    
    (value,name)=member.split("=")
    return "{}={}".format(name,value)

class SomeIPParser:
    def __init__(self,dir:str,target:str) -> None:
        self.__configDir=dir
        self.someIP:SomeIP=SomeIP()

    def parse(self):
        if not os.path.exists(os.path.join(self.__configDir,  "someip/SOMEIP.xlsx")):
            raise Exception("./someip/SOMEIP.xlsx not exist")
        excle: xlrd.book.Book = xlrd.open_workbook(
            os.path.join(self.__configDir,  "someip/SOMEIP.xlsx"))
        serviceSheet = excle.sheet_by_name("ServiceInfo")
        serviceId = serviceSheet.cell_value(1, 1)
        instanceSheet = excle.sheet_by_name("ServiceInstanceDefinition")
        instId = instanceSheet.cell_value(1, 1)
        self.someIP.setServiceInst(serviceId, hex(int(instId)))

        paraSheet = excle.sheet_by_name("Parameter")
        paraConfigSheet = excle.sheet_by_name("ParameterConfig")
        msgListSheet = excle.sheet_by_name("ServiceInterfaceDesign")

        i:int = 0
        msgDict: Dict[str, Message] = {}
        for rowIndex in range(1, msgListSheet.nrows):
            txECU = "SSoc"
            rxECU = "SSoc"
            msgName = msgListSheet.cell_value(rowIndex, 0).strip()
            methodId = msgListSheet.cell_value(rowIndex, 2)
            if methodId == "":
                methodId = "0x0"
            setterId = msgListSheet.cell_value(rowIndex, 4)
            if setterId == "/":
                setterId = "0x0"
            getterId = msgListSheet.cell_value(rowIndex, 6)
            if getterId == "/":
                getterId = "0x0"
            eventId = msgListSheet.cell_value(rowIndex, 8)
            if eventId == "/":
                eventId = "0x0"
            groupName = msgListSheet.cell_value(rowIndex,9).strip()
            groupName="EventGroup_"+groupName
            eventGroupID = msgListSheet.cell_value(rowIndex, 10)
            if eventGroupID != "/":
                self.someIP.addEvent(groupName, eventGroupID, eventId, msgName)
            else:
                eventGroupID = "0x0"
            protocol = msgListSheet.cell_value(rowIndex, 11)
            idtName = msgListSheet.cell_value(rowIndex, 14).strip()
            desc = msgListSheet.cell_value(rowIndex, 15).strip()

            msg = Message(txECU,rxECU,msgName,serviceId,hex(int(methodId,16)),hex(int(getterId,16)),hex(int(setterId,16)),hex(int(eventId,16)),hex(int(eventGroupID,16)),groupName,protocol=="TCP",idtName,desc)

            msgExit = msgDict.get(msgName, None)
            #method 有两行第二行是返回定义, 先忽略
            if msgExit == None:
                msgDict[msgName]=msg
            
            # print("%d: %s %s %s %s %s %s %s %s %s %s " % (i, msgName, methodId, setterId, getterId, eventId, 
            #         groupName, eventGroupID, protocol, idtName, desc))
            i += 1
            # if i > 10:
            #     break #for test
        
        for msg in msgDict.values():
            self.someIP.addMsg(msg)

        print("ServiceInterfaceDesign has {} lines".format(i))
        i = 0
        for rowIndex in range(1, paraSheet.nrows):
            idtName = paraSheet.cell_value(rowIndex, 0).strip()
            idtType = paraSheet.cell_value(rowIndex, 1).strip()
            if idtType == "type reference":
                idtType = paraSheet.cell_value(rowIndex, 2).strip()
            elementName = paraSheet.cell_value(rowIndex, 4).strip()
            elementType = paraSheet.cell_value(rowIndex, 5).strip()
            desc = paraSheet.cell_value(rowIndex, 7).strip()
            item = IdtItem(idtName, idtType, elementName, elementType, desc)
            self.someIP.addIdtItem(item)
            # print("%d: %s %s %s %s %s " % (i, idtName, idtType, elementName, elementType, desc))
            i += 1
            # if i > 130:
            #     break #for test
            
        print("Parameter has {} lines".format(i))
        # self.someIP.print()
        i = 0
        for rowIndex in range(1, paraConfigSheet.nrows):
            idtName = paraConfigSheet.cell_value(rowIndex, 0).strip()
            computeMethod = paraConfigSheet.cell_value(rowIndex, 1).strip()
            minValue = paraConfigSheet.cell_value(rowIndex, 2)
            maxValue = paraConfigSheet.cell_value(rowIndex, 3)
            name = paraConfigSheet.cell_value(rowIndex, 4).replace(" ", "")
            desc = paraConfigSheet.cell_value(rowIndex, 9)
            if computeMethod == "Text table" and name.isalnum() == False:
                name = name.split("（")[0]
                # if name.isalnum() == False:
                #     print("! ParameterConfig got except char:", name)
                #     continue
            
            try:
                item = EnumItem(idtName, computeMethod == "Text table", str(int(minValue)), str(int(maxValue)), name, desc)
            except ValueError as e:
                item = EnumItem(idtName, computeMethod == "Text table", str(float(minValue)), str(float(maxValue)), name, desc)
            except:
                print("Error unknow")
            
            if name.startswith("reserve") == False:
                self.someIP.addEnumItem(item)
            # print("%d: %s %d %s %s %s %s " % (i, idtName, computeMethod == "Text table", minValue, maxValue, name, desc))
            i += 1
            # if i > 10:
            #     break #for test
        print("ParameterConfig has {} lines".format(i))
        self.someIP.addIdtItemFromEnum()


    #返回需要透传的propertyName 以及相关连的enum定义
    def genertor_files(self):
        removeDir("./data/transfer/libsomeip")
        gen_someip_signal_id(self.someIP)
        gen_someip2SignalValue(self.someIP)
        gen_convert2someIp(self.someIP)
        gen_someip_manager(self.someIP)
        gen_SomeIPConfig(self.someIP)
        gen_NetSomeIP()
        gen_SomeIPConfigJson(self.someIP)
        gen_someip_Android_bp()
        gen_someip_object(self.someIP)
        gen_SomeIPProtoBuf(self.someIP)
        copyPackageTo("./data/transfer/libsomeip","../transfer/libsomeip")
        os.system("cp -r ./generator/libsomeip/serialize  ../transfer/libsomeip/include/")
        os.system("cp ./generator/libsomeip/ADCU_HmiService_types.h  ../transfer/libsomeip/include/")

    def toDirectTransmitImpl(self)->TypesHal:
        typesHal=TypesHal()
        #得到someip关于typeshal的定义
        names=[]
        for msg in self.someIP.msg:
            for item in [item for item in msg.item if item.isDirectTransmit()]:
                property=Property(item.msgName,True)
                if msg.isSend():
                    property.setAccessMode("WRITE")
                else:
                    property.setAccessMode("READ")
                property.setChangeMode("ON_CHANGE")
                property.setPropArea("GLOBAL")
                property.setPropType(item.toPropType())
                property.setDesc("")
                property.setPublisher(msg.txECU)
                property.setSubscriber(msg.rxECU)

                encodeType = item.encodeType
                # if item.msgName == "SIScPwSwUpdateInit":
                    
                if encodeType is not None:
                    property.setEncodeType(encodeType.getTypeName())
                    if encodeType.isEnum() and encodeType.getTypeName() not in names:
                        names.append(encodeType.getTypeName())
                        typesHal.addEnum(encodeType)
                else:
                    property.setEncodeType(item.payloadType.name)
                typesHal.addProperty(property)
        gen_SomeIPWriteDirectTransmitProperty(self.someIP)
        gen_SomeIPReadDirectTransmitProperty(self.someIP)
        return typesHal
